<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>8.模板方法模式</title>
</head>
<body>
	在模板方法模式中，子类实现中的相同部分被上移到父类中，而将不同的部分留待子类来实现
</body>
<script type="text/javascript">
	var Coffee = function(){}
	Coffee.prototype.boilWater = function() {
		console.log('把水煮沸');
	};
	Coffee.prototype.brewCoffeeGriends = function() {
		console.log('用沸水冲咖啡');
	};
	Coffee.prototype.pourIncup = function() {
		console.log('把咖啡倒进杯子');
	};
	Coffee.prototype.addSuguarAndMilk = function() {
		console.log('加糖和牛奶');
	};
	Coffee.prototype.init = function() {
		this.boilWater();
		this.brewCoffeeGriends();
		this.pourIncup();
		this.addSuguarAndMilk();
	};

	var coffee = new Coffee();
	coffee.init();



	/* 模板方法模式 */
	var Beverage = function(){}
	Beverage.prototype.boilWater = function() {
		console.log('把水煮沸');
	};

	Beverage.prototype.brew = function() {
		throw new Error('子类必须重写brew方法');
	};

	Beverage.prototype.pourIncup = function() {
		throw new Error('子类必须重写pourIncup方法');
	};

	Beverage.prototype.addCondiments = function() {
		throw new Error('子类必须重写addCondiments方法');
	};

	Beverage.prototype.init = function() {
		this.boilWater();
		this.brew();
		this.pourIncup();
		this.addCondiments();
	};

	var Coffee = function(){}
	Coffee.prototype = new Beverage();
	Coffee.prototype.brew = function() {
		console.log('用沸水冲咖啡');
	};
	Coffee.prototype.pourIncup = function() {
		console.log('把咖啡倒进杯子');
	};
	Coffee.prototype.addCondiments = function() {
		console.log('加糖和牛奶');
	};
	var coffee = new Coffee();
	coffee.init();

	var Tea = function(){}
	Tea.prototype = new Beverage();
	Tea.prototype.brew = function() {
		console.log('用沸水冲茶叶');
	};
	Tea.prototype.pourIncup = function() {
		console.log('把茶叶倒进杯子');
	};
	Tea.prototype.addCondiments = function() {
		console.log('加柠檬');
	};

	var tea = new Tea();
	tea.init();


	/* js模板方法模式 */
	var Beverage = function(param){
		var boilWater = function(){
			console.log('把水煮沸');
		}

		var brew = param.brew ||  function() {
			throw new Error('子类必须重写brew方法');
		};
		var pourInCup = param.pourInCup ||  function() {
			throw new Error('子类必须重写pourInCup方法');
		};
		var addCondiments = param.addCondiments ||  function() {
			throw new Error('子类必须重写addCondiments方法');
		};

		var F = function(){};

		F.prototype.init = function(){
			boilWater();
			brew();
			pourInCup();
			addCondiments();
		}
		return F;
	}

	var Coffee = Beverage({
		brew : function() {
			console.log('用沸水冲咖啡');
		},
		pourInCup : function() {
			console.log('把咖啡倒进杯子');
		},
		addCondiments : function() {
			console.log('加糖和牛奶');
		}
	});

	var Tea = Beverage({
		brew : function() {
			console.log('用沸水冲茶叶');
		},
		pourInCup : function() {
			console.log('把茶叶倒进杯子');
		},
		addCondiments : function() {
			console.log('加柠檬');
		}
	});

	var coffee = new Coffee();
	coffee.init();

	var tea = new Tea();
	tea.init();
</script>
</html>